package com.xianxing.service.user.service.impl;

import com.xianxing.common.pojo.AuthToken;
import com.xianxing.service.user.mapper.UserMapper;
import com.xianxing.service.user.pojo.User;
import com.xianxing.service.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;//以字符串形式存储
    @Autowired
    private UserMapper userMapper;

    /**
     * 用户授权
     * @param username
     * @param password
     * @param client
     * @param clientSecret
     * @return
     */
    @Override
    public AuthToken login(String username, String password, String client, String clientSecret) {

        //获取令牌
        //封装请求头
        LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        headers.add("Authorization",this.getHttpBsic(client,clientSecret));
        //封装请求体
        LinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type","password");
        body.add("username",username);
        body.add("password",password);
        //存入httpentity
        HttpEntity<MultiValueMap<String, String>> multiValueMapHttpEntity = new HttpEntity<>(body,headers);
        //设置错误请求
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if(response.getRawStatusCode()!=400&&response.getRawStatusCode()!=401){
                    super.handleError(response);
                }
            }
        });
        //发送请求
        String url="http://oauth2-server/oauth/token";
        ResponseEntity<Map> map = restTemplate.exchange(url, HttpMethod.POST, multiValueMapHttpEntity, Map.class);
        Map responseData = map.getBody();
        if(responseData==null||responseData.get("access_token")==null||responseData.get("refresh_token")==null){
            throw new RuntimeException("获取令牌失败");
        }
        //封装对象
        AuthToken authToken = new AuthToken();
        authToken.setJti(username);
        authToken.setAccess_token((String) responseData.get("access_token"));
        authToken.setRefresh_token((String)responseData.get("refresh_token"));
        authToken.setExpires_in(Long.valueOf(String.valueOf(responseData.get("expires_in"))));
        authToken.setScope((String)responseData.get("scope"));
        //存入redis
        stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccess_token(),authToken.getExpires_in(), TimeUnit.SECONDS);
        return authToken;
    }

    /**
     * 根据用户名查询用户
     * @param username
     * @return
     */
    @Override
    public User findUserByUsername(String username) {

        if(StringUtils.isEmpty(username)){
            return null;
        }
        //根据用户名查询用户
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName",username);
        User user = userMapper.selectOneByExample(example);

        return user;
    }

    /**
     * 获取httpbasic  basic client:clientSecret的base64编码
     * @param client
     * @param clientSecret
     * @return
     */
    private String getHttpBsic(String client, String clientSecret) {
            String value=client+":"+clientSecret;
            byte[] encode = Base64Utils.encode(value.getBytes());
            return "Basic "+new String(encode);

    }
}
